<route lang="json5" type="login">
{
  style: {
    navigationBarTitleText: '电子签名',
    navigationBarTextStyle: 'white', //标题栏字体颜色
    navigationBarBackgroundColor: '#0063AF', //标题栏背景色(纯色)
  },
}
</route>

<template>
  <view class="draw-wrap">
    <!-- 亲笔签名 -->
    <canvas
      canvas-id="canvasId"
      id="canvasId"
      class="canvasId"
      ref="canvasId"
      style="width: 100%; height: 100%"
      @touchstart="touchstart"
      @touchmove="touchmove"
      @touchend="touchend"
      disable-scroll="true"
    />
    <view class="tips" v-if="showTips">{{ $attrs.tips }}</view>
  </view>
  <view class="flex justify-center gap-4rpx">
    <wd-button type="success" @click="sub">保存</wd-button>

    <wd-button type="error" @click="resign">重置</wd-button>
  </view>
</template>

<script setup>
import { ref, getCurrentInstance, useAttrs, onMounted } from 'vue'

const attrs = useAttrs()
const canvasId = ref()
const showTips = ref(true) // 提示信息信号量
let points = [] // 存放绘制的连线点
let record = [] // 轨迹记录，方便取消上一次绘画
const id = ref(0) // 轨迹记录的id
const lineWidth = attrs.lineWidth ? attrs.lineWidth : 3 // 线宽
const lineColor = attrs.lineColor ? attrs.lineColor : 'black' // 线颜色
const lineCap = attrs.lineCap ? attrs.lineCap : 'round' // 线端点样式
const canvasBackgroundColor = attrs.canvasBackgroundColor ? attrs.canvasBackgroundColor : '#e3e4e7' // canvas背景颜色
const { proxy: t } = getCurrentInstance()
const canvaCtx = uni.createCanvasContext('canvasId', t)

onMounted(() => {
  // 设置背景颜色
  setBgc()
})

// 设置背景色
const setBgc = () => {
  canvaCtx.setFillStyle(canvasBackgroundColor) // 线端点样式
  canvaCtx.fillRect(0, 0, 1000, 1000)
  canvaCtx.draw(true)
}

// 触摸开始时获取起点
const touchstart = (e) => {
  id.value++
  const startX = e.changedTouches[0].x
  const startY = e.changedTouches[0].y
  const startPoint = {
    X: startX,
    Y: startY,
    id: id.value,
  }
  points.push(startPoint)
  record.push(startPoint)
  canvaCtx.beginPath()
  canvaCtx.setLineWidth(lineWidth) // 线宽
  canvaCtx.setStrokeStyle(lineColor) // 线颜色
  canvaCtx.setLineCap(lineCap) // 线端点样式
}

// 触摸移动获取路径点
const touchmove = (e) => {
  const moveX = e.changedTouches[0].x
  const moveY = e.changedTouches[0].y
  const movePoint = {
    X: moveX,
    Y: moveY,
    id: id.value,
  }
  points.push(movePoint)
  record.push(movePoint)
  showTips.value = false
  const len = points.length
  if (len >= 2) {
    draw() // 绘制路径
  }
}

// 触摸结束 清空
const touchend = (e) => {
  points = []
}

// 重签
const resign = () => {
  points = []
  record = []
  showTips.value = true
  canvaCtx.clearRect(0, 0, 2000, 2000)
  canvaCtx.draw(true)
  setBgc()
}

// 清除上一步
const back = () => {
  if (record.length === 0) return
  const lastId = record[record.length - 1].id
  // 再绘制
  record = record.filter((item) => item.id !== lastId)
  if (record.length === 0) {
    showTips.value = true
  }
  // 先清除
  canvaCtx.clearRect(0, 0, 2000, 2000)
  canvaCtx.draw(true)
  setBgc()
  canvaCtx.beginPath()
  record.reduce((prev, curr) => {
    if (prev.id !== curr.id) {
      canvaCtx.beginPath()
    } else {
      canvaCtx.moveTo(prev.X, prev.Y)
      canvaCtx.lineTo(curr.X, curr.Y)
      canvaCtx.stroke()
      canvaCtx.draw(true)
    }
    return curr
  }, record[0])
}

// 保存
const sub = () => {
  uni.canvasToTempFilePath({
    canvasId: 'canvasId',
    fileType: 'png',
    quality: 1,
    success(res) {
      if (record.length === 0) {
        uni.showToast({
          title: '您还没有签名!',
          icon: 'error',
          duration: 1000,
        })
      } else {
        uni.uploadFile({
          url: '/app-api/infra/file/upload', // 开发者服务器的URL
          filePath: res.tempFilePath,
          name: 'file', // 必填，文件对应的 key
          success: (res) => {
            const { data } = JSON.parse(res.data)
            const pages = getCurrentPages()
            const prevPage = pages[pages.length - 2] // 上一页页面实例
            console.log(prevPage)
            prevPage.$vm.url = data
            uni.navigateBack({
              delta: 1,
            })
          },
          fail: (uploadFileErr) => {
            toast.close()
            toast.error({
              msg: '识别失败，重新上传',
            })
            console.error('upload fail:', uploadFileErr)
          },
        })
      }
    },
  })
}

// 绘制线
const draw = () => {
  const point1 = points[0]
  const point2 = points[1]
  points.shift()
  canvaCtx.moveTo(point1.X, point1.Y)
  canvaCtx.lineTo(point2.X, point2.Y)
  canvaCtx.stroke()
  canvaCtx.draw(true)
}

// 暴露	重签	撤回	提交方法
defineExpose({
  resign,
  back,
  sub,
})
</script>

<style scoped>
.draw-wrap {
  padding: 20rpx;
  position: relative;
  width: 100%;
  height: 800rpx;
  box-sizing: border-box;
}

.tips {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 12px;
  pointer-events: none;
  font-weight: 1000;
  color: rgba(0, 0, 0, 0.4);
  letter-spacing: 2px;
}
</style>
